package com.zeus.cloud.logback;

import com.hengxinyongli.zeus.common.core.Aes;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.config.client.ConfigClientProperties;
import org.springframework.cloud.config.client.ConfigServicePropertySourceLocator;
import org.springframework.core.env.*;

import java.util.*;

/**
 * @author magic
 * @date 2018/9/29/029 14:24
 * @version 1.0
 * Description ZeusPropertySourceLocator
 */
public class ZeusPropertySourceLocator extends ConfigServicePropertySourceLocator {

    private static final String LOGBACK_PREFIX = "logback.";
    private static final String LOGBACK_LOAD_COMPLETE = "hasComplete";
    private static final String MATCH_PASSWORD = "password";
    private static final String AES_ENCRYPT_KEY = "aes.key";
    private static final String AES_ENCRYPT_KEY_DEFAULT = "!@#$%^&*QWERTYUI";
    private static final List<String> NEED_DECRYPT_LIST = Arrays.asList(MATCH_PASSWORD);
    private static Logger logger = LoggerFactory.getLogger(ZeusPropertySourceLocator.class);

    public ZeusPropertySourceLocator(ConfigClientProperties defaultProperties) {
        super(defaultProperties);
    }

//    public static void main(String[] args) throws Exception{
//        System.out.println(Aes.encrypt("123456",AES_ENCRYPT_KEY_DEFAULT));
//
//    }

    @Override
    public PropertySource<?> locate(Environment environment) {
        Properties properties = System.getProperties();
        String sKey = (String) properties.getOrDefault(AES_ENCRYPT_KEY,AES_ENCRYPT_KEY_DEFAULT);
        PropertySource propertySource = super.locate(environment);
        Map<String,Object> asModifySource = new HashMap<>(16);
        if (propertySource instanceof EnumerablePropertySource) {
            for (String key : ((EnumerablePropertySource) propertySource).getPropertyNames()) {
               parseLogbackKey(key,propertySource,properties);
               if(checkNeedDecrypt(key)){
                   try {
                       String decryptValue = Aes.decrypt((String) propertySource.getProperty(key),sKey);
                       asModifySource.put(key,decryptValue);
                       logger.info("PropertySource locate decrypt key {}  success ",key);
                   }catch (Exception e){
                       logger.error("PropertySource locate decrypt key {} ,error: {}",key, ExceptionUtils.getRootCauseMessage(e));
                   }
               }
            }
        }
        properties.put(LOGBACK_LOAD_COMPLETE, true);
        MapPropertySource mapPropertySource = new MapPropertySource("decryptSource",asModifySource);
        if(propertySource instanceof CompositePropertySource){
            ((CompositePropertySource) propertySource).addFirstPropertySource(mapPropertySource);
        }
        return propertySource;
    }

    private boolean checkNeedDecrypt(String key) {
        for (String match: NEED_DECRYPT_LIST) {
            if(key.indexOf(match) > 0){
                return true;
            }
        }
        return false;
    }

    private void parseLogbackKey(String key,PropertySource propertySource,Properties properties) {
        if (key.startsWith(LOGBACK_PREFIX)) {
            String renameKey = key.substring(LOGBACK_PREFIX.length());
            properties.put(renameKey, propertySource.getProperty(key));
        }
    }

}
